
var express = require("express");
var path = require("path");
var url = require("url");
var fsp = require("fs/promises");

// // 用于接收post数据  并对数据做处理(第三方 运行依赖)  => express已经内置
// var bodyParser = require("body-parser");  // 老版本

var app = express(); //创建服务器 


// 中间件: 在请求-响应周期中有权访问请求对象 （）、响应对象 （） 和函数的函数
// app.use(callback)  中间件函数接收一个回调函数
// callback  中间件函数,(回调函数有三个参数req,res,next), 
//        req  请求对象
//        res  响应对象
//        next  函数 => 继续执行中间函数中的下一个

// 中间件函数可以执行以下任务：
//     执行任何代码。
//     对请求和响应对象进行更改。
//     结束请求-响应周期。  res.end
//     调用堆栈中的下一个中间件。

// 注意: 
// 每次客户端向服务器发送请求时,会依次经过每一个中间件 (前提:中间件中调用next())
// 结束响应一般不和next同时出现, 响应结束后继续向后走没有意义)



// app.use(express.static(path.join(__dirname, "../site")));
// app.use(express.json());//用于解析application/json
// app.use(express.urlencoded({ extended: true }));   //用于解析application/x-www-urlencoded

express.myStatic = function (siteUrl) {

    var path = require("path");
    var fs = require("fs");
    var fsp = require("fs/promises");

    var site = siteUrl;  // 配置站点路径

    async function render(pathname, res) {

        // 对应url地址栏中路径部分 展示页面

        //(1) 默认从site文件夹中查找文件(site默认站点)    
        //(2) 不同类型的文件 输出不同的Content-Type格式
        //     分析: 不同类型的文件,后缀名不同 .css  .js .html .json .png .jpg .jpeg .gif
        var isExist = fs.existsSync(path.join(site, pathname)); //站点中是否存在文件/文件夹

        if (isExist) { // 传入的路径可能是站点中的文件 / 文件夹

            var info = fs.statSync(path.join(site, pathname)); // 获取路径信息 
            if (info.isFile()) {


                var ext = path.extname(pathname); // 获取地址栏路径部分的后缀名
                // console.log(ext);
                if (ext) {
                    var typeEnum = {
                        ".html": "text/html;charset=utf-8",
                        ".css": "text/css;charset=utf-8",
                        ".js": "text/javascript;charset=utf-8",
                        ".json": "text/json;charset=utf-8",
                        ".jpg": "image/jpg",
                        ".jpeg": "image/jpeg",
                        ".png": "image/png",
                        ".gif": "image/gif",
                        ".woff2": "application/octet-stream",
                    }

                    if (Object.keys(typeEnum).includes(ext)) {
                        res.writeHead(200, {
                            "Content-Type": typeEnum[ext],
                        })
                    }

                }

                var content = await fsp.readFile(path.join(site, pathname));
                // console.log(1111, content);

                res.write(content);

                res.end();  // 请求处理结束,返回响应的结果 (并关闭响应)   => res.end() 不建议重复调用
            } else if (info.isDirectory()) {
                // res.writeHead(200, {
                //     "Content-Type": "text/plain;charset=utf-8",
                // })
                // res.end("访问的是站点下文件夹,默认访问文件夹的主页面")
                pathname = path.join(pathname, "/index.html");
                render(pathname, res);
            }
        } else {
            next();
        }
    }

    return function (req, res, next) {  // 中间件函数
        render(req.pathname, res, next);
    }
}

// 全局中间件:   
// app.use("*",function(){})   每次客户端向服务器发送请求时,会依次经过每一个中间件
// app.use(function(){})    "*" 可以省略

// 局部中间件
// app.use("/xxx",function(){})   每次客户端向服务器发送请求时, 只有指定路由(路由),及其子路由才能执行对应的中间件

// list = [calback1,callback2,callback3];
app.use(function (req, res, next) {
    if (req.url != "/favicon.ico") { // 排除 favicon.ico
        console.log("接收到来自客户端的请求:", 1);
        next();
    } else {
        res.end();
    }
})

app.use(function (req, res, next) {
    console.log("接收到来自客户端的请求:", 2);

    next();
})

app.use(function (req, res, next) {
    console.log("接收到来自客户端的请求:", 3);

    next();
})

// app.use(express.myStatic(path.join(__dirname, "../site")));

app.use(function (req, res, next) {
    console.log("接收到来自客户端的请求:", 4);
    next();
})


// /  根路由
// /user  一级路由
// /user/add  二级路由

// 匹配一级路由及其子路由
// /user   /user/add    /user/add/a
app.use("/user", function (req, res, next) {
    console.log("接收到来自客户端的请求/user", "a");
    next();


})
app.use("/user", function (req, res, next) {
    console.log("接收到来自客户端的请求/user", "b");
    res.end("hello a");
})

app.use(function (req, res, next) {
    console.log("接收到来自客户端的请求:", 5);
    res.end("hello world");
})










// 监听端口
app.listen(3000, () => {
    console.log("服务启动=>  http://localhost:3000");
})




